﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Text;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Exercises
{

    [TestClass]
    public class ReactiveEvents
    {
        [TestMethod]
        public void ReportNextChangeToSubscribers()
        {
            //initialize
            var changes = new List<StatusChange>();
            var statusChangeReporter = new Subject<StatusChange>();
            statusChangeReporter.Subscribe(changes.Add);

            //execute
            var @event = new StatusChange { OrderId = 1 };
            statusChangeReporter.OnNext(@event);

            //assert
            Assert.AreEqual(@event, changes.Single());
        }

        [TestMethod]
        public void OnlyHearOrderId1()
        {
            //initialize
            var changes = new List<StatusChange>();
            var statusChangeReporter = new Subject<StatusChange>();
            statusChangeReporter.Where(x => x.OrderId == 1).Subscribe(changes.Add);

            //execute
            var events = Enumerable.Range(0, 10).Select(x => new StatusChange { OrderId = x });
            events.ToList().ForEach(statusChangeReporter.OnNext);

            //assert
            Assert.AreEqual(1, changes.Single().OrderId);
        }

        [TestMethod]
        public void HearErrorEvents()
        {
            //initialize
            var statusChangeReporter = new Subject<StatusChange>();
            Exception exception = null;
            statusChangeReporter.Subscribe(x => { }, ex => exception = ex);

            //execute
            statusChangeReporter.OnError(new Exception());

            //assert
            Assert.IsNotNull(exception);
        }

        [TestMethod]
        public void HearCompleteEvent()
        {
            //initialize
            var statusChangeReporter = new Subject<StatusChange>();
            var finished = false;
            statusChangeReporter.Subscribe(x => { }, ex => { }, () => finished = true);

            //execute
            statusChangeReporter.OnCompleted();

            //assert
            Assert.IsTrue(finished);
        }

        class StatusChange
        {
            public int OrderId { get; set; }
            public string OrderStatus { get; set; }
        }
    }
}
